package com.hifar.test.test.render;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.hifar.abi.utils.minio.MinioUtils;
import com.hifar.base.serialNo.service.IBaseSerialNoService;
import com.hifar.constant.SystemConsts;
import com.hifar.enums.ReportTypeEnum;
import com.hifar.fw.utils.id.IdUtils;
import com.hifar.idm.util.ConvertPdfUtil;
import com.hifar.plat.baseModal.service.IBaseOssFilesService;
import com.hifar.plugins.TextCheckBoxRenderPolicy;
import com.hifar.plugins.TimeRenderPolicy;
import com.hifar.sys.MinioUtil;
import com.hifar.test.task.pojo.HfEnvTask;
import com.hifar.test.task.service.IHfEnvTaskService;
import com.hifar.test.template.pojo.HfEnvTemplate;
import com.hifar.test.template.service.IHfEnvTemplateService;
import com.hifar.test.test.pojo.*;
import com.hifar.test.test.render.model.TestCurveDataRenderModel;
import com.hifar.test.test.service.*;
import com.hifar.test.unit.constant.UnitConstant;
import com.hifar.test.unit.pojo.HfPrjUnitBase;
import com.hifar.test.unit.service.IHfPrjUnitBaseService;
import org.apache.commons.io.FileUtils;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhuWeiWei
 * @description 环境原始记录渲染
 * @date 2025/6/09 10:38
 */
@Component
public class HfEnvOriginalRecordRender {
    @Autowired
    private IBaseOssFilesService baseOssFilesService;
    @Autowired
    private IHfEnvTestService testService;
    @Autowired
    private IHfEnvTemplateService envTemplateService;
    @Autowired
    private IBaseSerialNoService baseSerialNoService;
    @Autowired
    private IHfPrjUnitBaseService unitBaseService;
    @Autowired
    private IHfEnvTestPieceService testPieceService;
    @Autowired
    private IHfEnvTaskTestRelationService taskTestRelationService;

    @Autowired
    private IHfEnvTaskService taskService;

    @Autowired
    private IHfEnvTestCurveDataService testCurveDataService;

    @Autowired
    private IHfEnvTestPersonService testPersonService;


    /**
     * 渲染试验原始模板
     *
     * @param testId 试验id
     */
    public void renderReport(String testId) {
        HfEnvTest hfEnvTest = testService.getById(testId);
        String unitId = hfEnvTest.getUnitId();
        HfPrjUnitBase prjUnitBase = unitBaseService.getById(unitId);
        Assert.notNull(prjUnitBase, "试验项目数据不存在!");
        String unitType = prjUnitBase.getUnitType();
        HfEnvTemplate reportTemplate = null;
        if (Objects.equals(UnitConstant.TYPE_DYNAMICS, unitType)) {
            reportTemplate = envTemplateService.getTemplateByType(ReportTypeEnum.DYNAMICS_ORIGINAL_RECORDS);
            Assert.notNull(reportTemplate, "力学原始记录模板不存在!");
        } else {
            reportTemplate = envTemplateService.getTemplateByType(ReportTypeEnum.CLIMATE_ORIGINAL_RECORDS);
            Assert.notNull(reportTemplate, "气候原始记录模板不存在!");
        }
        String templatePath = reportTemplate.getTemplatePath();
        String originalCode = baseSerialNoService.getMouthSerialNo(testId + "Original"
                , "yyyyMMdd", "YS-", "", 2);
        File tempDirectory = FileUtils.getTempDirectory();
        String templateLocalPath = tempDirectory + File.separator + IdUtils.uuid32() + ".docx";
        String tempPdfPath = null;
        File tempWordFile = null;
        try {
            String wordObjectName = "hifar/idm/" + originalCode + ".docx";
            String pdfObjectName = "hifar/idm/" + originalCode + ".pdf";
            
            // 下载模板文件
            try {
                MinioUtil.downloadFile(MinioUtil.PRE_DEFAULT, templatePath, templateLocalPath);
            } catch (Exception e) {
                throw new RuntimeException("模板文件下载失败: " + e.getMessage(), e);
            }
            
            // 封装数据
            Map<String, Object> pageData = null;
            try {
                pageData = this.packageData(testId);
            } catch (Exception e) {
                throw new RuntimeException("试验数据封装失败: " + e.getMessage(), e);
            }
            
            // 渲染Word文档
            try {
                tempWordFile = this.render(new File(templateLocalPath), pageData);
            } catch (Exception e) {
                throw new RuntimeException("Word文档渲染失败: " + e.getMessage(), e);
            }
            
            // 转换PDF
            try {
                tempPdfPath = ConvertPdfUtil.wordToPdf(tempWordFile.getAbsolutePath());
            } catch (Exception e) {
                throw new RuntimeException("PDF转换失败，请检查转换服务: " + e.getMessage(), e);
            }
            
            // 上传文件到MinIO
            try {
                MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, wordObjectName, tempWordFile.getAbsolutePath());
                MinioUtils.uploadLocalFileToMinio(MinioUtil.PRE_DEFAULT, pdfObjectName, tempPdfPath, "application/pdf");
            } catch (Exception e) {
                throw new RuntimeException("文件上传失败，请检查MinIO服务: " + e.getMessage(), e);
            }

            // 更新数据库
            try {
                UpdateWrapper<HfEnvTest> testUpdateWrapper = new UpdateWrapper<>();
                testUpdateWrapper.lambda()
                        .set(HfEnvTest::getPdfPathXh, pdfObjectName)
                        .set(HfEnvTest::getDocxPathXh, wordObjectName)
                        .eq(HfEnvTest::getId, testId);
                testService.update(testUpdateWrapper);
            } catch (Exception e) {
                throw new RuntimeException("数据库更新失败: " + e.getMessage(), e);
            }
        } catch (RuntimeException e) {
            e.printStackTrace();
            // 内层已经包装了详细错误信息，直接抛出
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            // 未预期的其他异常
            throw new RuntimeException("原始记录生成过程中发生未知错误: " + e.getMessage(), e);
        } finally {
            if (new File(templateLocalPath).exists()) {
                new File(templateLocalPath).delete();
            }
            if (Objects.nonNull(tempWordFile)) {
                tempWordFile.delete();
            }
            if (Objects.nonNull(tempPdfPath)) {
                new File(tempPdfPath).delete();
            }
        }
    }

    private File render(File templateFile, Map<String, Object> data) throws Exception {
        ConfigureBuilder builder = Configure.builder();
        Configure configure = builder.build();
        File tempDirectory = FileUtils.getTempDirectory();

        String tempWordPath = tempDirectory + File.separator + IdUtils.uuid32() + ".docx";
        HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
        // < 注册为表格渲染
        LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy();
        TimeRenderPolicy timeRenderPolicy2 = new TimeRenderPolicy("yyyy-MM-dd-");
        TimeRenderPolicy timeRenderPolicy3 = new TimeRenderPolicy("yyyy-MM-dd HH:mm");
        TextCheckBoxRenderPolicy textCheckBoxRenderPolicy = new TextCheckBoxRenderPolicy();
        TextCheckBoxRenderPolicy yesTextCheckBoxRenderPolicy2 = new TextCheckBoxRenderPolicy(SystemConsts.YES);
        TextCheckBoxRenderPolicy noTextCheckBoxRenderPolicy = new TextCheckBoxRenderPolicy(SystemConsts.NO);

        builder.addPlugin('<', loopRowTableRenderPolicy);
        builder.addPlugin(':', timeRenderPolicy2);
        builder.addPlugin('$', timeRenderPolicy3);
        builder.addPlugin('-', textCheckBoxRenderPolicy);
        builder.addPlugin('=', yesTextCheckBoxRenderPolicy2);
        builder.addPlugin('!', noTextCheckBoxRenderPolicy);
        builder.bind("testCondition", htmlRenderPolicy);
        // 日期渲染插件配置
        Configure.ClearHandler clearHandler = new Configure.ClearHandler();
        builder.useSpringEL(false);
        builder.setValidErrorHandler(clearHandler);
        XWPFTemplate
                .compile(templateFile.getPath(), configure)
                .render(data)
                .writeAndClose(new FileOutputStream(tempWordPath));
        return new File(tempWordPath);
    }

    private Map<String, Object> packageData(String testId) {
        Map<String, Object> dataMap = new HashMap<>();
        HfEnvTest hfEnvTest = testService.getById(testId);
        Assert.notNull(hfEnvTest, "试验数据不存在!");
        String unitName = hfEnvTest.getUnitName();
        dataMap.put("unitName", unitName);

        List<HfEnvTestPiece> testPieceList = testPieceService.listPieceByTestId(testId);

        Set<String> productNameSet = new HashSet<>();
        Set<String> productCodeSet = new HashSet<>();
        Set<String> productNoSet = new HashSet<>();

        for (HfEnvTestPiece hfEnvTestPiece : testPieceList) {
            productNameSet.add(hfEnvTestPiece.getProductName());
            productCodeSet.add(hfEnvTestPiece.getProductCode());
            productNoSet.add(hfEnvTestPiece.getPieceNo());
        }
        // 产品名称
        dataMap.put("productName", String.join(",", productNameSet));
        dataMap.put("productCode", String.join(",", productCodeSet));
        dataMap.put("pieceNo", String.join(",", productNoSet));
        dataMap.put("pieceNum", testPieceList.size());

        List<HfEnvTaskTestRelation> taskTestRelationList = taskTestRelationService.lambdaQuery()
                .eq(HfEnvTaskTestRelation::getTestId, testId)
                .list();
        List<String> taskIdList = taskTestRelationList.stream()
                .map(HfEnvTaskTestRelation::getTaskId)
                .collect(Collectors.toList());
        List<HfEnvTask> taskList = taskService.listByIds(taskIdList);

        List<String> standardNameList = new ArrayList<>();
        List<String> standardCodeList = new ArrayList<>();
        List<String> testConditionList = new ArrayList<>();
        for (HfEnvTask hfEnvTask : taskList) {
            standardNameList.add(hfEnvTask.getStandardName());
            testConditionList.add(hfEnvTask.getTestCondition());
            standardCodeList.add(hfEnvTask.getStandardCode());
        }
        String standardNames = String.join(",", standardNameList);
        String standardCodes = String.join(",", standardCodeList);
        String testConditions = String.join(",", testConditionList);
        dataMap.put("standardNames", standardNames);
        dataMap.put("standardCodes", standardCodes);
        dataMap.put("testConditions", testConditions);

        List<HfEnvTestCurveData> testCurveDataList = testCurveDataService.listByTestId(testId);
        Iterator<HfEnvTestCurveData> testCurveDataIterator = testCurveDataList.iterator();

        int testCurveNum = (testCurveDataList.size() / 2) + (testCurveDataList.size() % 2);
        List<TestCurveDataRenderModel> testCurveDataRenderModelList = new ArrayList<>(testCurveDataList.size() / 2 + 1);
        for (int i = 0; i < testCurveNum; i++) {
            TestCurveDataRenderModel testCurveDataRenderModel = new TestCurveDataRenderModel();
            if (testCurveDataIterator.hasNext()) {
                HfEnvTestCurveData testCurveData = testCurveDataIterator.next();
                testCurveDataRenderModel.setSettingValue1(testCurveData.getTemperature());
                testCurveDataRenderModel.setDisplayValue1(testCurveData.getHumidity());
                testCurveDataRenderModel.setOptUserId1(testCurveData.getOptUserId());
                testCurveDataRenderModel.setOptUserName1(testCurveData.getOptUserName());
                testCurveDataRenderModel.setRecordTime1(testCurveData.getRecordTime());
            }
            if (testCurveDataIterator.hasNext()) {
                HfEnvTestCurveData testCurveData = testCurveDataIterator.next();
                testCurveDataRenderModel.setSettingValue2(testCurveData.getTemperature());
                testCurveDataRenderModel.setDisplayValue2(testCurveData.getHumidity());
                testCurveDataRenderModel.setOptUserId2(testCurveData.getOptUserId());
                testCurveDataRenderModel.setOptUserName2(testCurveData.getOptUserName());
                testCurveDataRenderModel.setRecordTime2(testCurveData.getRecordTime());
            }
            testCurveDataRenderModelList.add(testCurveDataRenderModel);
        }

        dataMap.put("curveList", testCurveDataRenderModelList);
        dataMap.put("equipCode", hfEnvTest.getEquipCode());
        dataMap.put("equipModel", hfEnvTest.getEquipModel());
        dataMap.put("equipName", hfEnvTest.getEquipName());
        dataMap.put("checkValid", hfEnvTest.getCheckValid());
        dataMap.put("realStartTime", hfEnvTest.getRealStartTime());
        dataMap.put("realEndTime", hfEnvTest.getRealEndTime());
        dataMap.put("remarks", hfEnvTest.getRemarks());
        dataMap.put("testCode", hfEnvTest.getTestCode());
        dataMap.put("testResult", hfEnvTest.getTestResult());
        dataMap.put("processDesc", hfEnvTest.getProcessDesc());
        dataMap.put("humidity", hfEnvTest.getHumidity());
        dataMap.put("temperature", hfEnvTest.getTemperature());

        List<HfEnvTestPerson> testPersonList = testPersonService.listTestTestUser(testId);
        String testUserName = testPersonList.stream()
                .map(HfEnvTestPerson::getUserName)
                .collect(Collectors.joining(","));
        dataMap.put("testUserName", testUserName);
        return dataMap;
    }


}
